package com.translate.web.api.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import com.translate.entity.NoticeCenter;
import com.translate.vo.UserVO;
import org.springframework.beans.BeanUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.NativeWebRequest;
import com.translate.vo.NoticeVO;
import com.response.vo.ResponseModel;
import com.controller.base.AbstractCommonController;
import com.page.PageResponseData;
import com.translate.web.param.NoticeUpdateParam;
import com.translate.web.param.UserIdParam;
import com.translate.web.param.NoticeAddParam;
import com.translate.entity.Notice;
import com.translate.entity.NoticeReaded;
import com.translate.web.service.INoticeCenterService;
import com.translate.web.service.INoticeReadedService;
import com.translate.web.service.INoticeService;
import com.translate.web.service.INoticeUserService;
import com.basic.service.contract.IBaseService;
import com.common.util.ListConvertMap;
import com.common.util.MergeDataSource;

@RestController
@RequestMapping("notice")
public class NoticeController extends AbstractCommonController<Notice, UserIdParam> {
	private INoticeService service;
	
	private INoticeCenterService centerService;
	
	private INoticeUserService userService;
	
	private INoticeReadedService readedService;
	
	

	public NoticeController(INoticeService service) {
		this.service = service;
	}
	
	@Override
	protected void frontProcesserVO(UserIdParam param, NativeWebRequest object) {
		param.setSelectCount(100);
		int userId = (int) this.getUserId(object);
		param.setUserId(userId);
		
		super.frontProcesserVO(param, object);
	}


	protected <VO> PageResponseData<VO> afterProcesserVO(
		PageResponseData<VO> orderList,
		UserIdParam param) 
	{
		long total = orderList.getTotal();
		
		List<VO> data = orderList.getData();
		
		if (0 == total) {
			
			staticsRewardUser(orderList, param, data);
			
			return orderList;
		}
		
		int[] ids = data.stream().mapToInt((e) -> ((NoticeVO)e).getId()).toArray();
		
		List<NoticeReaded> selectNotice = readedService.selectNotice(ids, param.getUserId());
		
		
		Map<Integer, NoticeReaded> listToMap = ListConvertMap.listToMap(selectNotice, NoticeReaded::getNoticeId);
		
		MergeDataSource<VO> mergeDataSource = new MergeDataSource<VO>(data);
		
		mergeDataSource.mergeRelease((e) -> ((NoticeVO)e).getId(), listToMap, (item, read) -> {
			
			NoticeVO vo = (NoticeVO) item;
			
			vo.setReadStatus((byte) 1);
			
			return item;
		});
		
		staticsRewardUser(orderList, param, data);

		//时间倒序
		List<NoticeVO> userList = new ArrayList<>();
		for (VO vo : data) {
			NoticeVO noticeVO = new NoticeVO();
			BeanUtils.copyProperties(vo,noticeVO);
			userList.add(noticeVO);
		}
		int n = userList.size();
		boolean swapped;
		for (int i = 0; i < n - 1; i++) {
			swapped = false;
			for (int j = 0; j < n - 1 - i; j++) {
				if (userList.get(j).getCreateTime() < userList.get(j + 1).getCreateTime()) {
					// 交换 list[j] 和 list[j+1]
					NoticeVO temp = userList.get(j);
					userList.set(j, userList.get(j + 1));
					userList.set(j + 1, temp);
					swapped = true;
				}
			}
			// 如果没有发生交换，列表已经有序
			if (!swapped) break;
		}

		orderList.setData((List<VO>) userList);
		
		return orderList;
	}

	protected <VO> void staticsRewardUser(PageResponseData<VO> orderList, UserIdParam param, List<VO> data) {
		
		int pageNum = param.getPageNum();
		if (1 == pageNum) {
			int maxId = this.centerService.getMaxId();
			
			int lastId = (maxId) / pageNum;
			
			param.setLastId(lastId);
		}
		
		
		int num = centerService.countRewardUser(param.getUserId());

		List<VO> noticeCentersByUserId = centerService.noticeCentersByUserId(param, this.getTarget());

		orderList.setTotal(orderList.getTotal() + num);
		
		data.addAll(noticeCentersByUserId);

	}
	
	
	/**
	 * 添加
	 * @param <V>
	 * @param param
	 * @return
	 */
	@PostMapping("/add")
	public ResponseModel<Integer> insert(@RequestBody @Validated NoticeAddParam param,
			HttpServletRequest httpServletRequest) {
		int id = this.service.parseInsert(param, Notice.class);

		return ResponseModel.<Integer>success(id);
	}
	
	@PostMapping("/countNumber")
	public ResponseModel<Map<String, Integer>> countNum(NativeWebRequest httpServletRequest) {
		long userId = this.getUserId(httpServletRequest);
		
		// 消息未读中心总数
		int num = centerService.countNotRead((int) userId);
		
		
		// 平台未读消息总数
		int countNumber = service.countNumber((int) userId);
		
		// 各个类型的消息总数 0订单消息 1 系统消息 2 体现消息（其他）
		Integer[] countOrderAndSecondaryServiceNotice = this.centerService.countOrderAndSecondaryServiceNotice((int) userId);
		
		int totalNum = countNumber+ num;
		
		Map<String, Integer> map = new HashMap<String, Integer>();
		
		map.put("totalNum", totalNum);
		
		map.put("orderNum", countOrderAndSecondaryServiceNotice[0]);
		
		map.put("systemNum", countOrderAndSecondaryServiceNotice[1]);
		
		map.put("otherNum", countOrderAndSecondaryServiceNotice[2] + countNumber);
		
		return ResponseModel.success(map);
	}
	

	@Override
	protected IBaseService<Notice> getBaseService() {
		return this.service;
	}

	/**
	 * 添加
	 * 
	 * @param <V>
	 * @param param
	 * @return
	 */
	@PostMapping("/update")
	public ResponseModel<Integer> update(@Validated @RequestBody NoticeUpdateParam param,
			HttpServletRequest httpServletRequest) {
		int res = this.service.parseUpdate(param, Notice.class);
		return ResponseModel.<Integer>success(res);
	}

	protected <VO> Class<VO> getTarget() {
		return (Class<VO>) NoticeVO.class;
	}

	@Resource
	public void setReadedService(INoticeReadedService readedService) {
		this.readedService = readedService;
	}
	
	@Resource
	public void setCenterService(INoticeCenterService centerService) {
		this.centerService = centerService;
	}
	
	@Resource
	public void setUserService(INoticeUserService userService) {
		this.userService = userService;
	}
}